/**
 * @title JedisClusterClient.java
 * @package com.hopechart.plugin.redis
 * @description TODO
 * @author daijiang@hopechart.com
 * @date 2016年7月6日 下午4:21:40
 * @version v1.0.0
 * @copyright 杭州鸿泉数字设备有限公司
 */
package com.aokser.redisplugin.redis;

import com.aokser.redisplugin.exception.RedisPluginException;
import com.aokser.redisplugin.util.SerializationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * 集群版客户端
 * @version 1.0
 * @author daijiang@hopechart.com
 */
@Component
public class JedisClusterClient {

    @Autowired
    JedisClusterFactory jedisClusterFactory;

    public JedisCluster getJedisCluster() {
        try {
            return jedisClusterFactory.getObject();
        } catch (Exception e) {
            throw new RedisPluginException("获取JedisCluster对象时发生异常！", e);
        }
    }

    /***************************API******************************/

    public void validateJedisCluster() {
        if(null == getJedisCluster()) {
            throw new IllegalArgumentException("JedisCluster对象为空，请检查注入配置！");
        }
    }

    public void subscribe(RedisPluginSubscribe redisPluginSubscribe, String channel) {
        try {
            getJedisCluster().subscribe(redisPluginSubscribe, channel);
        } catch (Exception e) {
            subscribe(redisPluginSubscribe, channel);
        }
    }

    public void close() {
        /*
        try {
            getJedisCluster().close();
        } catch (IOException e) {
        }
        */
    }

    /**
     * 根据Key获取String类型数据
     * @param key 键值
     * @return String
     */
    public String get(String key) {
        try {
            return getJedisCluster().get(key);
        } finally {
            close();
        }
    }

    /**
     * 根据Key获取String类型数据
     * @param key 键值
     * @return byte[]
     */
    public byte[] get(byte[] key) {
        try {
            return getJedisCluster().get(key);
        } finally {
            close();
        }
    }

    /**
     * 设置String类型的数据
     * @param key 键值
     * @param value 数据
     */
    public void set(String key, String value) {
        try {
            getJedisCluster().set(key, value);
        } finally {
            close();
        }
    }

    /**
     * 设置String类型的数据
     * @param key 键值
     * @param value 数据
     */
    public void set(byte[] key, byte[] value) {
        try {
            getJedisCluster().set(key, value);
        } finally {
            close();
        }
    }

    /**
     * 删除指定的key
     * @param key 键值
     */
    public void del(String key) {
        try {
            getJedisCluster().del(key);
        } finally {
            close();
        }
    }

    /**
     * 删除指定key的数据
     * @param key 键值
     */
    public void del(byte[] key) {
        try {
            getJedisCluster().del(key);
        } finally {
            close();
        }
    }

    /**
     * 从头部添加元素
     * @param key 键值
     * @param value 数据
     */
    public void lpush(String key, String value) {
        try {
            getJedisCluster().lpush(key, value);
        } finally {
            close();
        }
    }

    /**
     * 从头部添加元素
     * @param key 键值
     * @param value 数据
     */
    public void lpush(byte[] key, byte[] value) {
        try {
            getJedisCluster().lpush(key, value);
        } finally {
            close();
        }
    }

    /**
     * 从尾部添加元素
     * @param key 键值
     * @param value 数据
     */
    public void rpush(String key, String value) {
        try {
            getJedisCluster().rpush(key, value);
        } finally {
            close();
        }
    }

    /**
     * 从尾部添加元素
     * @param key 键值
     * @param value 数据
     */
    public void rpush(byte[] key, byte[] value) {
        try {
            getJedisCluster().rpush(key, value);
        } finally {
            close();
        }
    }

    /**
     * 从list 的头部删除元素，并返回删除元素
     * @param key 键值
     * @return String
     */
    public String lpop(String key) {
        try {
            return getJedisCluster().lpop(key);
        } finally {
            close();
        }
    }

    /**
     * 从list 的头部删除元素，并返回删除元素
     * @param key 键值
     * @return byte[]
     */
    public byte[] lpop(byte[] key) {
        try {
            return getJedisCluster().lpop(key);
        } finally {
            close();
        }
    }

    /**
     * 从list 的尾部删除元素，并返回删除元素
     * @param key 键值
     * @return String
     */
    public String rpop(String key) {
        try {
            return getJedisCluster().rpop(key);
        } finally {
            close();
        }
    }

    /**
     * 从list 的尾部删除元素，并返回删除元素
     * @param key 键值
     * @return byte[]
     */
    public byte[] rpop(byte[] key) {
        try {
            return getJedisCluster().rpop(key);
        } finally {
            close();
        }
    }

    /**
     * 返回key 对应list 的长度
     * @param key 键值
     * @return Long
     */
    public Long llen(String key) {
        try {
            return getJedisCluster().llen(key);
        } finally {
            close();
        }
    }

    /**
     * 返回key 对应list 的长度
     * @param key 键值
     * @return Long
     */
    public Long llen(byte[] key) {
        try {
            return getJedisCluster().llen(key);
        } finally {
            close();
        }
    }

    /**
     * 返回存储在 key 的列表里指定范围内的元素
     * @param key 键值
     * @param start 起始索引
     * @param end 结束索引
     * @return List<String>
     */
    public List<String> lrange(String key, long start, long end) {
        try {
            return getJedisCluster().lrange(key, start, end);
        } finally {
            close();
        }
    }

    /**
     * 返回存储在 key 的列表里指定范围内的元素
     * @param key 键值
     * @param start 起始索引
     * @param end 结束索引
     * @return List<byte[]>
     */
    public List<byte[]> lrange(byte[] key, long start, long end) {
        try {
            return getJedisCluster().lrange(key, start, end);
        } finally {
            close();
        }
    }

    /**
     * 向名称为key 的set 中添加元素
     * @param key 键值
     * @param value 数据集
     */
    public void sadd(String key, String ... value) {
        try {
            getJedisCluster().sadd(key, value);
        } finally {
            close();
        }
    }

    /**
     * 向名称为key 的set 中添加元素
     * @param key 键值
     * @param value 数据集
     */
    public void sadd(byte[] key, byte[] ... value) {
        try {
            getJedisCluster().sadd(key, value);
        } finally {
            close();
        }
    }

    /**
     * 删除名称为key 的set 中的元素member
     * @param key 键值
     */
    public void srem(String key) {
        try {
        } finally {
            close();
        }
    }

    /**
     * 删除名称为key 的set 中的元素member
     * @param key 键值
     */
    public void srem(byte[] key) {
        try {
        } finally {
            close();
        }
    }

    /**
     * 返回名称为key 的set 的元素个数
     * @param key 键值
     * @return long
     */
    public long scard(String key) {
        try {
            return getJedisCluster().scard(key);
        } finally {
            close();
        }
    }

    /**
     * 返回名称为key 的set 的元素个数
     * @param key 键值
     * @return long
     */
    public long scard(byte[] key) {
        try {
            return getJedisCluster().scard(key);
        } finally {
            close();
        }
    }

    /**
     * 返回所有成员
     * @param key 键值
     * @return Set<byte[]>
     */
    public Set<String> smembers(String key) {
        try {
            return getJedisCluster().smembers(key);
        } finally {
            close();
        }
    }

    /**
     * 返回所有成员
     * @param key 键值
     * @return Set<byte[]>
     */
    public Set<byte[]> smembers(byte[] key) {
        try {
            return getJedisCluster().smembers(key);
        } finally {
            close();
        }
    }

    /**
     * 设置hash field 为指定值，如果key 不存在，则先创建
     * @param key 键值
     * @param field 字段
     * @param value 数据
     */
    public void hset(String key, String field, String value) {
        try {
            getJedisCluster().hset(key, field, value);
        } finally {
            close();
        }
    }

    /**
     * 设置hash field 为指定值，如果key 不存在，则先创建
     * @param key 键值
     * @param field 字段
     * @param value 数据
     */
    public void hset(byte[] key, byte[] field, byte[] value) {
        try {
            getJedisCluster().hset(key, field, value);
        } finally {
            close();
        }
    }

    /**
     * 获取指定的hash field
     * @param key 键值
     * @param field 字段
     * @return String
     */
    public String hget(String key, String field) {
        try {
            return getJedisCluster().hget(key, field);
        } finally {
            close();
        }
    }

    /**
     * 获取指定的hash field
     * @param key 键值
     * @param field 字段
     * @return byte[]
     */
    public byte[] hget(byte[] key, byte[] field) {
        try {
            return getJedisCluster().hget(key, field);
        } finally {
            close();
        }
    }

    /**
     * 返回hash 的所有value
     * @param key 键值
     * @return List<String>
     */
    public List<String> hvals(String key) {
        try {
            return getJedisCluster().hvals(key);
        } finally {
            close();
        }
    }

    /**
     * 返回hash 的所有value
     * @param key 键值
     * @return Collection<byte[]>
     */
    public Collection<byte[]> hvals(byte[] key) {
        try {
            return getJedisCluster().hvals(key);
        } finally {
            close();
        }
    }

    /**
     * 返回hash 的所有field
     * @param key 键值
     * @return Set<String>
     */
    public Set<String> hkeys(String key) {
        try {
            return getJedisCluster().hkeys(key);
        } finally {
            close();
        }
    }

    public Set<String> keys(String key) {
        try {
            return null;
        } finally {
            close();
        }
    }

    public Set<byte[]> keys(byte[] key) {
        try {
            return null;
        } finally {
            close();
        }
    }

    /**
     * 返回hash 的所有field
     * @param key 键值
     * @return Set<byte[]>
     */
    public Set<byte[]> hkeys(byte[] key) {
        try {
            return getJedisCluster().hkeys(key);
        } finally {
            close();
        }
    }

    /**
     * 返回指定hash 的field 数量
     * @param key 键值
     * @return long
     */
    public long hlen(String key) {
        try {
            return getJedisCluster().hlen(key);
        } finally {
            close();
        }
    }

    /**
     * 返回指定hash 的field 数量
     * @param key 键值
     * @return long
     */
    public long hlen(byte[] key) {
        try {
            return getJedisCluster().hlen(key);
        } finally {
            close();
        }
    }

    /**
     * 删除指定hash 的field
     * @param key 键值
     * @param field 字段
     * @return long
     */
    public long hdel(String key, String field) {
        try {
            return getJedisCluster().hdel(key, field);
        } finally {
            close();
        }
    }

    /**
     * 删除指定hash 的field
     * @param key 键值
     * @param field 字段
     * @return long
     */
    public long hdel(byte[] key, byte[] field) {
        try {
            return getJedisCluster().hdel(key, field);
        } finally {
            close();
        }
    }

    /**
     * 反序列化
     * @param bytes 字节数据
     * @return Object
     */
    public Object deserialize(byte[] bytes) {
        return SerializationUtil.hessianDeserialize(bytes);
    }

    /**
     * 序列化
     * @param obj 待序列化对象
     * @return byte[]
     */
    public byte[] serialize(Object obj) {
        return SerializationUtil.hessianSerialize(obj);
    }

    /**
     * 发布
     * @param channel 通道
     * @param message 消息
     */
    public void publish(byte[] channel, byte[] message) {
        try {
            getJedisCluster().publish(channel, message);
        } finally {
            close();
        }
    }

    /**
     * 发布
     * @param channel 通道
     * @param message 消息
     */
    public void publish(String channel, String message) {
        try {
            getJedisCluster().publish(channel, message);
        } finally {
            close();
        }
    }

    /**
     * 生成递增的整数值
     * @param key
     * @return long
     */
    public long incr(String key) {
        try {
            return getJedisCluster().incr(key);
        } finally {
            close();
        }
    }

    /**
     * 生成递增的整数值
     * @param key
     * @return long
     */
    public long incr(byte[] key) {
        try {
            return getJedisCluster().incr(key);
        } finally {
            close();
        }
    }

    public String type(String key) {
        try {
            return getJedisCluster().type(key);
        } finally {
            close();
        }
    }

    /**
     * 获取节点数
     * @return int
     */
    public int getNodesSize() {
        return getJedisCluster().getClusterNodes().size();
    }

    public JedisClusterFactory getJedisClusterFactory() {
        return jedisClusterFactory;
    }

    public void setJedisClusterFactory(JedisClusterFactory jedisClusterFactory) {
        this.jedisClusterFactory = jedisClusterFactory;
    }
}
